package com.springcloud.auth.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.DigestUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class TokenHelper {

    private static final Logger log = LoggerFactory.getLogger(TokenHelper.class);
    /**
     * 用来签名的秘钥
     */
    private static String SECRET = "sdmsdgh254eysdlfnsdou";

    private static String urlEncodeToUtf8(String str) {
        try {
            return URLEncoder.encode(str, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static String urlDecodeFromUtf8(String str) {
        try {
            return URLDecoder.decode(str, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static String base64Encode(String str) {
        return Base64
                .getEncoder()
                .encodeToString(str.getBytes(StandardCharsets.UTF_8));
    }

    private static String base64Decode(String str) {
        return new String(Base64.getDecoder().decode(str), StandardCharsets.UTF_8);
    }

    /**
     * 生成签名
     * @param str
     * @return
     */
    private static String sign(String str) {
        return DigestUtils.md5DigestAsHex((str + SECRET).getBytes());
    }

    /**
     * 生成带有客户端IP信息的token
     * @param payload
     * @return
     */
    public static String generateToken(Map<String, String> payload) {
        String payloadStrOri = payload
                .entrySet()
                .stream()
                .filter( line -> line.getValue()!=null && line.getValue().trim().length() > 0 )
                .sorted(Map.Entry.comparingByKey())
                .map(e -> urlEncodeToUtf8(e.getKey()) + '=' + urlEncodeToUtf8(e.getValue()))
                .collect(Collectors.joining("&"));
        String payloadStr = base64Encode(payloadStrOri.toString());
        return payloadStr + "." + sign(payloadStr);
    }

    /**
     * 验证token是否合法, 以及给出原始的payload
     * @param token
     * @return
     */
    public static TokenEntity validateToken(String token) {
        String[] array = token.split("[.]");
        String payloadStr = array[0];
        String signed = array[1];
        Map<String, String> payload = parseToken(payloadStr);
        Boolean isValid = generateToken(payload).equals(payloadStr + "." + signed);
        return new TokenEntity(isValid, payload);
    }

    private static Map<String, String> parseToken(String payloadStr) {
        String payload = base64Decode(payloadStr);
        Map<String, String> data = new HashMap<>();
        Arrays.stream(payload.split("&")).forEach(e -> {
            String[] keyValArr = e.split("=");
            data.put(urlDecodeFromUtf8(keyValArr[0]), keyValArr.length > 1 ? urlDecodeFromUtf8(keyValArr[1]) : "");
        });
        return data;
    }

}
